package org.eclipse.nebula;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.resource.DeviceResourceManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.osgi.framework.Bundle;

/**
 * 
 * 
 * @since 1.0.0
 */
public class NebulaImages {

	private static ImageRegistry imageRegistry;

	/**
	 * The path to the icons in the resources.
	 */
	private final static String ICONS_PATH = "/icons/";//$NON-NLS-1$

	/**
	 * Map of Display onto DeviceResourceManager. Holds all the resources for
	 * the associated display.
	 */
	private static final Map<Display, ResourceManager> registries = new HashMap<Display, ResourceManager>();

	/** ... TODO Javadoc ... */
	public static final String IMG_ADD_INFO = "add";

	/** ... TODO Javadoc ... */
	public static final String IMG_REMOVE_INFO = "remove";
	
	/** ... TODO Javadoc ... */
	public static final String IMG_TIME_ENTRY = "timeEntry";

	/**
	 * Creates a new Image Registry if the internal instance does not exist.
	 * 
	 * @return imageRegistry the internal instance of the image registry.
	 */
	public static ImageRegistry getImageRegistry() {
		if (imageRegistry == null) {
			imageRegistry = new ImageRegistry(getResources(Display.getCurrent()));
			initializeDefaultImages();
		}
		return imageRegistry;
	}

	/**
	 * 
	 */
	private static void initializeDefaultImages() {
		Object bundle = null;
		try {
			bundle = NebulaActivator.getBundle();
		} catch (NoClassDefFoundError exception) {
			// Test to see if OSGI is present
		}

		declareImage(bundle, IMG_ADD_INFO, ICONS_PATH + "timetext/add.gif"); //$NON-NLS-1$
		declareImage(bundle, IMG_REMOVE_INFO, ICONS_PATH + "timetext/remove.gif"); //$NON-NLS-1$
		declareImage(bundle, IMG_TIME_ENTRY, ICONS_PATH + "timetext/clock.gif"); //$NON-NLS-1$
	}

	/**
	 * Returns the image in JFace's image registry with the given key, or
	 * <code>null</code> if none. Convenience method equivalent to
	 * 
	 * <pre>
	 * JFaceResources.getImageRegistry().get(key)
	 * </pre>
	 * 
	 * @param key
	 *            the key
	 * @return the image, or <code>null</code> if none
	 */
	public static Image getImage(String key) {
		return getImageRegistry().get(key);
	}

	/**
	 * Returns the ResourceManager for the current display. May only be called
	 * from a UI thread.
	 * 
	 * @since 3.1
	 * 
	 * @return the global ResourceManager for the current display
	 */
	public static ResourceManager getResources() {
		return getResources(Display.getCurrent());
	}

	/**
	 * Returns the global resource manager for the given display
	 * 
	 * @since 3.1
	 * 
	 * @param toQuery
	 *            display to query
	 * @return the global resource manager for the given display
	 */
	public static ResourceManager getResources(final Display toQuery) {
		ResourceManager reg = (ResourceManager) registries.get(toQuery);
		if (reg == null) {
			final DeviceResourceManager mgr = new DeviceResourceManager(toQuery);
			reg = mgr;
			registries.put(toQuery, reg);
			toQuery.disposeExec(new Runnable() {
				public void run() {
					mgr.dispose();
					registries.remove(toQuery);
				}
			});
		}
		return reg;
	}

	/**
	 * Declares a JFace image given the path of the image file (relative to the
	 * JFace plug-in). This is a helper method that creates the image descriptor
	 * and passes it to the main <code>declareImage</code> method.
	 * 
	 * @param bundle
	 *            the {@link Bundle} or <code>null</code> of the Bundle cannot
	 *            be found
	 * @param key
	 *            the symbolic name of the image
	 * @param path
	 *            the path of the image file relative to the base of the
	 *            workbench plug-ins install directory
	 * @param fallback
	 *            the {@link Class} where the fallback implementation of the
	 *            image is relative to
	 * @param fallbackPath
	 *            the path relative to the fallback {@link Class}
	 * 
	 */
	private static final void declareImage(Object bundle, String key, String path) {

		ImageDescriptor descriptor = null;

		if (bundle != null) {
			URL url = FileLocator.find((Bundle) bundle, new Path(path), null);
			if (url != null)
				descriptor = ImageDescriptor.createFromURL(url);
		}

		imageRegistry.put(key, descriptor);
	}

}
